﻿using Common;
using Microsoft.EntityFrameworkCore;
using PLC.Domain.Enum;
using PLC.Domain.Models;
using PLC.Domain.ScheduledTasks;
using PLC.Domain.Service.IRepository;
using Serilog;
using System;
using PLC.Domain.Dto;

namespace PLC.Domain.Service.Service;

public class PLCOperationService
{
    private readonly IPLCRepository _plcRepository;
    private readonly IDeviceConfigRepository _deviceConfigRepository;

    public PLCOperationService(IPLCRepository plcRepository,IDeviceConfigRepository deviceConfigRepository)
    {
        _plcRepository = plcRepository?? throw new ArgumentNullException(nameof(plcRepository));
        _deviceConfigRepository = deviceConfigRepository?? throw new ArgumentNullException(nameof(deviceConfigRepository));
    }
    /// <summary>
    /// 往plc中写数据
    /// </summary>
    /// <param name="plcOperationModel"></param>
    /// <returns></returns>
    /// <exception cref="Exception"></exception>
    public Task WritePLCData(PLCOperationModel plcOperationModel)
    {
        var client = PLCHelper.Get(plcOperationModel.Ip)??throw new Exception("找不到对应ip的客户端");
        _plcRepository.WriteData(client,plcOperationModel.Register,plcOperationModel.Value,
            (EnumDataType)plcOperationModel.DataType,(EnumDataEncoding)plcOperationModel.Encoding,plcOperationModel.Length,(EnumProtocol)plcOperationModel.Protocol);
        return Task.CompletedTask;
    }
    /// <summary>
    /// 读取plc中的数据
    /// </summary>
    /// <param name="plcOperationModel"></param>
    /// <returns></returns>
    /// <exception cref="Exception"></exception>
    public Task<PLCOperationModel> ReadPLCData(PLCOperationModel plcOperationModel)
    {
        var client = PLCHelper.Get(plcOperationModel.Ip) ?? throw new Exception("找不到对应ip的客户端");
        var result =  _plcRepository.ReadData(client, plcOperationModel.Register, (EnumDataType)plcOperationModel.DataType,
            (EnumDataEncoding)plcOperationModel.Encoding, plcOperationModel.Length);
        plcOperationModel.Value = result;
        return Task.FromResult(plcOperationModel);
    }
   
    /// <summary>
    /// 切换配方
    /// </summary>
    /// <param name="recipe"></param>
    /// <returns></returns>
    public async Task SwitchRecipe(int recipe)
    {
        var config = Appsettings.app<OperationalConfig>("OperationalConfig");
        if (config==null||string.IsNullOrWhiteSpace(config.SelectRecipeBit)||string.IsNullOrWhiteSpace(config.ConfirmFormulaBit))
        {
            throw new Exception("找不到配置，请检查是否配置！");
        }
        var selectAddress =config.SelectRecipeBit;
        var confirmAddress =config.ConfirmFormulaBit;
        var ipList = await _deviceConfigRepository.Qyery.Where(p => !p.IsDelete).Select(p => p.Ip).Distinct().ToListAsync();
        foreach (var ip in ipList)
        {
            var client = PLCHelper.Get(ip);
            if (client != null)
            {
                try
                {
                    _plcRepository.WriteData(client, selectAddress, recipe.ToString(), EnumDataType.整数16位);
                    _plcRepository.WriteData(client, confirmAddress, "1", EnumDataType.整数16位);
                }
                catch (Exception e)
                {
                    //这边报错就不抛出了 
                    //如果是多台plc 可能有的会不开机 然后连接不上
                    Log.Error(e,$"{ip}修改配方失败");
                }
            }
        }
    }

    public async Task<IList<DtoFormula>> FindFormulas()
    {
        var config = Appsettings.app<OperationalConfig>("OperationalConfig");
        if (config == null || string.IsNullOrWhiteSpace(config.CurrentFormulaNameBit)||string.IsNullOrWhiteSpace(config.CurrentFormulaValueBit))
        {
            throw new Exception("找不到配置，请检查是否配置！");
        }

        var ipList = await _deviceConfigRepository.Qyery.Where(p => !p.IsDelete).Select(p => p.Ip).Distinct().ToListAsync();
        var list = new List<DtoFormula>();
        foreach (var ip in ipList)
        {
            var client = PLCHelper.Get(ip);
            if (client != null)
            {
                try
                {
                    var value = _plcRepository.ReadData(client, config.CurrentFormulaValueBit, EnumDataType.整数16位).ToInt32();
                    var name = _plcRepository.ReadData(client, config.CurrentFormulaNameBit, EnumDataType.字符串,
                        EnumDataEncoding.ASCII, 50);
                    list.Add(new DtoFormula()
                    {
                        DeviceName = name,
                        FormulaValue = value
                    });
                }
                catch (Exception e)
                {
                    //这边报错就不抛出了 
                    //如果是多台plc 可能有的会不开机 然后连接不上
                    Log.Error(e, $"{ip}查询配方失败");
                }
            }
        }
        return list;
    } 
    /// <summary>
    /// 修改任务编号
    /// </summary>
    /// <param name="taskCode"></param>
    /// <exception cref="Exception"></exception>
    public async Task ChangeTaskCode(string taskCode)
    {
        ArgumentException.ThrowIfNullOrEmpty(taskCode);
        var config = Appsettings.app<OperationalConfig>("OperationalConfig");
        if (config == null || string.IsNullOrWhiteSpace(config.TaskCodeBit) )
        {
            throw new Exception("找不到配置，请检查是否配置！");
        }
        
        var ipList = await _deviceConfigRepository.Qyery.Where(p => !p.IsDelete).Select(p => p.Ip).Distinct().ToListAsync();
        foreach (var ip in ipList)
        {
            var client = PLCHelper.Get(ip);
            if (client != null)
            {
                try
                {
                    _plcRepository.WriteData(client, config.TaskCodeBit, taskCode, EnumDataType.字符串, 
                        EnumDataEncoding.ASCII, 50, EnumProtocol.欧姆龙EtherNet);
                }
                catch (Exception e)
                {
                    //这边报错就不抛出了 
                    //如果是多台plc 可能有的会不开机 然后连接不上
                    Log.Error(e, $"{ip}修改配方失败");
                }
            }
        }
    }
}